﻿using System;

namespace paiban.data
{
    using SanlieHash.Fast;
    using xlstool;

    public class WorkTable
    {
        internal int days;
        internal int work_count;
        internal string[] work_table;
        internal WorkPersonInfo info;
        internal int now_day = 1;
        internal int work_table_count;
        public WorkTable(WorkPersonInfo info, int work_count)
        {
            this.info = info;
            this.days = info.days;
            this.work_count = work_count;
            work_table_count = days * work_count;
            work_table = new string[work_table_count];
        }
        public void Goto(int day)
        {
            now_day = day;
        }
        public IEnumerable<int> LoopWorkNo()
        {
            for (var i = 0; i < work_count; i++) yield return i;
        }
        public void Edit(int work_no, string person) { Edit(now_day, work_no, person); }
        public void Edit(int day, int work_no, string person)
        {
            work_table[(day-1)*work_count + work_no] = person;
        }
        public string Read(int work_no) { return Read(now_day, work_no); }
        public string Read(int day, int work_no)
        {
            return work_table[(day - 1) * work_count + work_no];
        }
        public int ReadCount(string person) {  return ReadCount(now_day, person); }
        public int ReadCount(int day, string person)
        {
            int i, j;
            int count = 0;
            for (i = 0, j = (day - 1) * work_count; i < work_count; i++, j++) if (person== work_table[j]) count++;

            return count;
        }
        public bool HasPerson(string person) { return HasPerson(now_day, person); }
        public bool HasPerson(int day, string person)
        {
            int i, j;
            for (i = 0, j = (day - 1) * work_count; i < work_count; i++, j++) if (person == work_table[j]) return true;
            return false;
        }
        public IEnumerable<string> ReadPerson() { return ReadPerson(now_day); }
        public IEnumerable<string> ReadPerson(int day)
        {
            for (var i = 0; i < info.work_person_count; i++) if (HasPerson(day, info.work_person_map[i])) yield return info.work_person_map[i];
        }
        public IEnumerable<int> ReadPersonWorkNo(string person) { return ReadPersonWorkNo(now_day, person); }
        public IEnumerable<int> ReadPersonWorkNo(int day, string person)
        {
            int i, j;
            for (i = 0, j = (day - 1) * work_count; i < work_count; i++, j++) if (person == work_table[j]) yield return i;
        }
        public IEnumerable<string> ReadPersonByWorkNo(int workno)
        {
            for (var i = 0; i < days; i++) yield return work_table[i * work_count + workno];
        }
        public int WorkCount(int workno, string person)
        {
            var count = 0;
            foreach (var day in info.LoopDays()) if (Read(day, workno) == person) count++;
            return count;
        }
        public int WorkCount(string person)
        {
            var count = 0;
            for(var i = 0; i < work_table_count; i ++) if (work_table[i] == person) count++;
            return count;
        }
        public IEnumerable<int> WorkDays(int workno, string person)
        {
            foreach (var day in info.LoopDays()) if (Read(day, workno) == person) yield return day;
        }
        public string CalcHash()
        {
            return FastGuoMi.GetSM3(string.Join("+", work_table));
        }
        public void SaveCSV(string csv_name)
        {
            using (var file = File.Create($"./{csv_name}.csv"))
            {
                var writer = new StreamWriter(file);
                writer.Write($"日期,");
                for (var i = 0; i < work_count; i++) writer.Write($"{i+1},");
                writer.WriteLine();

                foreach (var day in info.LoopDays())
                {
                    writer.Write($"{info.month}月{day}日,");
                    for (var i = 0; i < work_count; i++) writer.Write($"{Read(day, i)},");
                    writer.WriteLine();
                }
                writer.Flush();
            }
        }
        public void SaveExcel(string name)
        {
            var xls = new Excel2003File();
            var pb = xls.GetWorkbook().ToSheet("排班表");
            FillExcelSheet(pb);
            using (var f = File.Create($"./{name}.xls")) xls.ToStream(f);
        }

        public void FillExcelSheet(Excel2003Sheet pb)
        {
            var rowno = 1;
            var row = pb.ToRow(rowno);
            row.ToCell(1).SetValue("日期");
            foreach (var workno in LoopWorkNo()) row.ToCell(1 + workno + 1).SetValue($"任务 {workno + 1}");

            foreach (var day in info.LoopDays())
            {
                rowno++;
                row = pb.ToRow(rowno);
                row.ToCell(1).SetValue($"{info.month}月{day}日");

                foreach (var workno in LoopWorkNo()) row.ToCell(1 + workno + 1).SetValue(Read(day, workno));
            }
        }
    }
}
